#include <reg51.h>
#include <stdio.h>
#include "control.h"
#include "light.h"
#include "steppermotor.h"

int i;
int doorCtrl = 0, doorProtect;

void listenKey() interrupt 2
{
    int key = P0 & 0xf;
    if (key < 8)
    {
        PushButton_Outside(key);
    }
    else if (key < 12)
    {
        PushButton_Inside(key - 8);
    }
    else if (key == 14)
        doorCtrl = 1;
    else if (key == 15)
        doorCtrl = 2;
    else if (key == 12)
        doorProtect = 1;
}
int upBit(int layer)
{
    return (layer - 1) << 1; // 对应层数的向上led的在P1中的位置
}
int downBit(int layer)
{
    return ((layer - 1) << 1) | 1; // 对应层数的向下led的在P1中的位置
}
int take(int curLayer, int runDirect)
{
    unsigned char outsideQuery = ~P1; // allQuery楼层请求,取反P1便于处理
    unsigned char insideQuery = ~P2;
    if (outsideQuery & (1 << upBit(curLayer)) && (runDirect >= 0)) // 对应楼层有向上请求且不与运行方向相反
    {
        P1 |= 1 << upBit(curLayer); // 取消对应亮灯
        P2 |= 1 << (curLayer - 1);
        return 1;
    }
    else if (outsideQuery & (1 << downBit(curLayer)) && (runDirect <= 0))
    {
        P1 |= 1 << downBit(curLayer);
        P2 |= 1 << (curLayer - 1);
        return 1;
    }
    else if (insideQuery & (1 << (curLayer - 1)))
    {
        P2 |= 1 << (curLayer - 1);
        return 1;
    }
    else
        return 0;
}
int lookUp(int curLayer)
{                                     // 返回是否存在上方请求
    unsigned char outsideQuery = ~P1; // allQuery楼层请求,取反P1便于处理
    unsigned char insideQuery = ~P2;
    curLayer += 1;
    for (; curLayer <= 4; curLayer++)
    {
        if (outsideQuery & (1 << upBit(curLayer)))
        { // 对应楼层有向上请求
            return 1;
        }
        if (outsideQuery & (1 << downBit(curLayer)))
        { // 对应楼层有向下请求
            return 1;
        }
        if (insideQuery & (1 << (curLayer - 1)))
        {
            return 1;
        }
    }
    return 0;
}
int lookDown(int curLayer)
{                                     // 返回最近的下方楼层请求
    unsigned char outsideQuery = ~P1; // allQuery楼层请求,取反P1便于处理
    unsigned char insideQuery = ~P2;
    curLayer -= 1;
    for (; curLayer >= 1; curLayer--)
    {
        if (outsideQuery & (1 << upBit(curLayer)))
        { // 对应楼层有向上请求
            return 1;
        }
        if (outsideQuery & (1 << downBit(curLayer)))
        { // 对应楼层有向下请求
            return 1;
        }
        if (insideQuery & (1 << (curLayer - 1)))
        {
            return 1;
        }
    }
    return 0;
}
void doorProc()
{
    int tmp;
    Stop();
    Delay_ms(500);
protect:
    OpenDoor();
    doorCtrl = 0;
    for (tmp = 0; tmp < 200; tmp++) // doorCtrl受按钮控制
    {
        Delay_ms(10);
        if (doorCtrl == 1)
            tmp = 0, doorCtrl = 0;
        else if (doorCtrl == 2)
        {
            doorCtrl = 0;
            break;
        }
    }
    CloseDoor();
    doorProtect = 0;
    for (tmp = 0; tmp < 50; tmp++) // 开始关门0.5秒内出发保护则重新开门
    {
        Delay_ms(10);
        if (doorProtect)
            goto protect;
    }
}
int main()
{
    int runDirect = 0, layer = 1;
    int existUp, existDown, idleCnt = 0,taked=0; 
    Initial();
    ShowShumaguan(1, 10);
    ShowShumaguan(2, 12);
    ShowShumaguan(3, 15);
    ShowShumaguan(4, 1);
    P0 = 0xff;
    P1 = 0xff;
    P2 = 0xFF;
    EA = 1;
    EX1 = 1;
    IT1 = 1;

    // 如果当前层有顺向则开门，关门
    // 决定运行方向，运行一层
    while (1)
    {
        taked=0;
        if (take(layer, runDirect) || (runDirect == 0 && doorCtrl == 1)) // 当前层有顺向请求或者要求开门
        {                  
            doorProc();// 开门上客
            taked=1;
        }
        existUp = lookUp(layer);      // 上方有请求
        existDown = lookDown(layer);  // 下方有请求
        if (existUp && runDirect > 0) // 上方有请求且正在向上，继续向上
            ;
        else if (existDown && runDirect < 0) // 下方有请求且正在向下
            ;
        else
        { // 无同向请求,向有请求的方向运行，都没有就停止
            if (existUp)
                runDirect = 1;
            else if (existDown)
                runDirect = -1;
            else
                runDirect = 0;
            if (take(layer, runDirect)&&taked==0)
            { // 如果方向改变了，原来不能上车的可能也上车了，修正一下
                doorProc();
                taked=1;
            }
        }
        // 实际运行
        if (runDirect == 0)
        { // 连续停止10s后，回到一楼
            Delay_ms(50);
            if (++idleCnt == 200)
            { // 15s
                if (layer != 1)
                {
                    P2 ^= 1;
                }
                idleCnt = 0;
            }
        }
        else
        {
            idleCnt = 0;
            if (runDirect > 0)
                Up(++layer);
            else if (runDirect < 0)
                Down(--layer);
        }
    }
}
